package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
)

//start tcp listener
func StartTcpServe() {
	Addr, _ := net.ResolveTCPAddr("tcp4", ":9999")
	listener, err := net.ListenTCP("tcp4", Addr)
	if err != nil {
		log.Error("start tcp listen error > %v", err)
		panic(err)
	}
	log.Info("start tcp listen")
	defer func() {
		log.Info("server is close")
		if err := listener.Close(); err != nil {
			log.Error("listener.Close() error (%v)", err)
		}
	}()
	for {
		conn, err := listener.AcceptTCP()
		log.Info("start accept <%s>", conn.RemoteAddr().Network())
		if err != nil {
			log.Error("listener.AcceptTCP() error(%v)", err)
			continue
		}
		go handleTCPConn(conn)
		log.Info("accept finished")
	}
}

func handleTCPConn(conn *net.TCPConn) {
	defer conn.Close()
	addr := conn.RemoteAddr().String()
	log.Info("<%s> handleTCPConn start", addr)
	for {
		data := ReadData(conn)
		if len(data) == 0 {
			//log.Warn("no data recv <%s>", addr)
			return
		}
		ParseCMD(data, conn)
	}
}

//读取网络数据
func ReadData(conn net.Conn) []byte {
	var data bytes.Buffer
	var buf [1024]byte
	for {
		n, err := conn.Read(buf[0:])
		if err != nil {
			if err == io.EOF {
				log.Info("recv done")
				//fmt.Println("recv error:" + err.Error())
				break
			} else {
				log.Warn("recv data error <%v>", err)
				return nil
			}
		}
		if buf[n-1] == '\n' {
			data.Write(buf[0 : n-1])
			break
		} else {
			data.Write(buf[0:n])
		}

	}
	return data.Bytes()

}

//发送网络数据
func SendData(conn net.Conn, data []byte) error {
	data = append(data, '\n')
	_, err := conn.Write(data)
	if err != nil {
		//fmt.Println("send error" + err.Error())
		return err
	}
	return nil
}

/*
	0：更新客户端版本或监控配置项
	1：保留
	2：心跳
	3：获取客户端运行时信息
*/

func ParseCMD(s []byte, conn net.Conn) {
	var pack map[string]interface{}
	data := strings.TrimSpace(string(s))
	addr := conn.RemoteAddr().String()
	if !strings.Contains(data, "type") {
		log.Error("<%s> protol error ", addr)
		return
	}
	if err := json.Unmarshal([]byte(data), &pack); err != nil {
		log.Error("<%s> data format error,can not unmarshal", addr)
		return
	}
	switch pack["type"] {
	case "0":
		log.Info("recv command , start update monitor config")
		PullConfig()
		/*
			主动执行插件指令，已取消
				case "1":
					res := Task(pack)
					err := SendData(conn, res)
					if err != nil {
						log.Error("send data error <%v>", err)
						return
					}
		*/
	case "2":
		log.Info("recv headbeart")
	case "3":
		bf := len(MonitorResult)
		err := SendData(conn, []byte(fmt.Sprintf("Monitor Queue length: %v", bf)))
		if err != nil {
			log.Error("send data error <%v>", err)
			return
		}
	default:
		log.Warn("<%s> protocol error", addr)
		return
	}
}

//旧版执行插件方法，已停止使用
func Task(m map[string]interface{}) []byte {
	var command string
	var args []string
	CurrentPath, _ := exec.LookPath(os.Args[0])
	pth := filepath.Dir(CurrentPath)
	if res, ok := m["plugin"].(string); ok {
		command = pth + "/plugin/" + string(res)
	}
	if res, ok := m["args"].(string); ok {
		args = strings.Split(res, " ")
	}
	log.Info("exec command:%s,args:%s", command, args)
	result, err := exec.Command(command, args...).Output()
	var res = make(map[string]interface{})
	if err != nil {
		log.Warn("exec plugin error <%v>", err)
		res["status"] = 1
		res["message"] = err.Error()
		result, _ := json.Marshal(res)
		return result
	}
	json.Unmarshal(result, &res)
	res["status"] = 0
	res["date"] = time.Now().Unix()
	result, _ = json.Marshal(res)
	return result
}

//执行插件并返回结果
func RunPlugin(s *Service) []byte {
	var args []string
	var command string
	CurrentPath, _ := exec.LookPath(os.Args[0])
	pth := filepath.Dir(CurrentPath)
	command = pth + "/plugin/" + s.Plugin
	args = strings.Split(s.Args, " ")
	result, err := exec.Command(command, args...).Output()
	var res = make(map[string]interface{})
	var tmp = make(map[string]interface{})
	//执行失败返回错误信息，是否有必要？
	if err != nil {
		log.Warn("exec plugin error <%v>", err)
		res["type"] = "4"
		res["status"] = 1
		res["message"] = err.Error()
		result, _ := json.Marshal(res)
		return result
	}
	//插件返回格式不正确直接返回nil
	if err := json.Unmarshal(result, &tmp); err != nil {
		return nil
	}
	//过滤服务端不需要收集的item
	for k, _ := range tmp {
		f := false
		for _, item := range s.Items {
			if k == item.Key {
				f = true
				break
			}
		}
		if f == false {
			delete(tmp, k)
		}
	}
	//过滤后的结果集为空则直接返回nil
	if len(tmp) == 0 {
		return nil
	}
	res["data"] = tmp
	res["host"] = host.Ip
	res["type"] = "4"
	res["service"] = s.Name
	res["status"] = 0
	res["date"] = time.Now().Unix()
	result, _ = json.Marshal(res)
	return result
}
